from flask import url_for
from flask_restful import Resource
from sqlalchemy import func

from model import db
from model.crud import QueryPaginatedPosts, QueryMultipleInstances
from model.tables import Blog, User, Follow, Like
from restful.data import DataPaginatePosts
from restful.request import Get
from restful.response import ResponseSuccess
from restful.session import login_required, data, current_user_required


def _PostsList(posts):
    ret=[]
    for i in posts:
        userdetail_data=Get(url_for('userdetail',uid=i.uid,_external=True))
        postlike_data=Get(url_for('postlike',pid=i.id,_external=True))

        ret.append({
        'pid':i.id,
        'time':i.time,
        'sort':i.sort,
        'title':i.title,
        'author': userdetail_data['username'],
        'author_icon_url':userdetail_data['img_icon'],
        'get_likes':len(postlike_data['get_likes'])
        })
    return ret


class PostsListBySort(Resource):
    @login_required
    @data({
        'sort': {
            'required': True,
            'type': str,
            'regex': r'^(交友|交易|求助)$',
            'help': '类别必须是 交友、交易或求助其中之一'
        },
        **DataPaginatePosts()
    })
    def get(self, data):
        sort = data['sort']
        limit = data['limit']
        offset = data['offset']
        asc = data['asc']

        query = Blog.query.filter_by(sort=sort, checked=True,passed=True)
        blogs,offset = QueryPaginatedPosts(query,limit,asc,offset)


        return ResponseSuccess(data={
            'blogs':_PostsList(blogs),
            'offset':offset,
        })


class PostsListBySimilar(Resource):
    @login_required
    @current_user_required
    @data({
        **DataPaginatePosts()
    })
    def get(self, data,current_user):
        limit = data['limit']
        offset = data['offset']
        asc = data['asc']

        similar_user=QueryMultipleInstances(User,{'role':current_user.role})

        query = Blog.query.filter(
            Blog.checked == True,
            Blog.passed == True,
            Blog.uid.in_([user.id for user in similar_user]),
            Blog.uid != current_user.id
        )

        blogs,offset = QueryPaginatedPosts(query,limit,asc,offset)

        return ResponseSuccess(data={
            'blogs':_PostsList(blogs),
            'offset':offset,
        })

class PostsListByMyFollowing(Resource):
    @login_required
    @current_user_required
    @data({
        **DataPaginatePosts()
    })
    def get(self, data,current_user):
        limit = data['limit']
        offset = data['offset']
        asc = data['asc']

        my_following =QueryMultipleInstances(Follow,{'uid':current_user.id})

        query = Blog.query.filter(
            Blog.checked == True,
            Blog.passed == True,
            Blog.uid.in_([i.uid1 for i in my_following]))

        blogs,offset = QueryPaginatedPosts(query,limit,asc,offset)

        return ResponseSuccess(data={
            'blogs':_PostsList(blogs),
            'offset':offset,
        })

class PostsListByTopHot(Resource):
    @login_required
    def get(self):
        results = (
            db.session.query(
                Blog,
                func.count(Like.pid).label('get_likes')
            )
            .join(Like, Blog.id == Like.pid)
            .filter(Blog.checked == True, Blog.passed == True)
            .group_by(Blog)
            .order_by(func.count(Like.pid).desc())
            .limit(10)
            .all()
        )

        blogs = [blog for blog, likes_count in results]

        return ResponseSuccess(data={
            'blogs':_PostsList(blogs),
        })


class PostsListByTopRecent(Resource):
    @login_required
    def get(self):
        results = (
            db.session.query(
                Blog,
            )
            .filter(Blog.checked == True, Blog.passed == True)
            .order_by(Blog.time.desc())
            .limit(10)
            .all()
        )
        blogs = [blog for blog in results]
        return ResponseSuccess(data={
            'blogs': _PostsList(blogs),
        })